<?php

/*!
	\file class.SimpleDBOSearch.php
	\brief Contains the class definition for SimpleDBOSearch
*/

/*!
	\class SimpleDBOSearch
	\brief Class for performing simple and advanced searches on a table.
*/
class SimpleDBOSearch
{
	private $search_criteria = "";	//!< String of MySQL syntax used for performing advanced searching (see SimpleDBOSearch::AddSearchCriteria() and SimpleDBOSearch::Search())
	private $sort_col        = "";  //!< Name of the column to sort by when searching the table
	private $sort_order      = "";	//!< Sort order (ASC, DESC) of sort_col
	private $limit_offset    = "";  //!< First row number to return when searching the table
	private $limit_count     = "";	//!< Last row number to return when searching the table
	
	private $sql;					//!< SQL Object for interacting with the database
	private $obj;					//!< DBO instance that this class will use to do the searching on
	
	/*!
		\brief Class Constructor
		\returns SimpleDBOSearch object
	*/
	public function __construct($obj)
	{
		// TODO: This ought to cache the SQL object.
		$this->sql = new SQL();
		$this->obj = $obj;
	}
		
	/*!
		\brief Sets the name of the column to sort by and the order method to use when searching the database
		\param $colname - name of the column to order results by
		\param $order - either ASC or DESC
		\returns nothing
	*/
	public function SetSortOrder($colname, $order)
	{
		$this->sort_col = $colname;
		$this->sort_order = $order;
	}
	
	/*!
		\brief Sets the row offset and number of rows to return when searching the databse.
		\param $limit_min - Row offset to start from
		\param $num_rows - Number of rows to return (optional)
		\returns nothing
	*/
	public function SetLimit($limit_min, $num_rows="")
	{
		$this->limit_offset = $limit_min;
		$this->limit_count = $num_rows;
	}
	
	/*!
		\brief Adds some criteria to the SimpleDBO's search query string
		\param $colname    - name of the column to perform the search on
		\param $query_text - pattern to find in the column
		\param $bool_op    - only necessary if adding multiple search criterias; boolean operator used to join the new criteria with the previous statement
		\param $logical_op - logical operator for the select ("=", "!=", "LIKE", etc)
		\returns nothing
		
		For more advanced searching.
	*/
	public function AddSearchCriteria($colname, $query_text, $logical_op="=", $bool_op="AND")
	{
		$query_text = $this->sql->Escape($query_text);
		$phrase = "(`{$colname}` {$logical_op} '{$query_text}') ";
		$this->search_criteria .= ($this->search_criteria == "") ? $phrase : "{$bool_op} $phrase ";
	}
	
	/*!
		\brief Executes the search
		\returns SimpleDBOResultSet, or false (if failed, or the search criteria string is empty)
	*/
	public function Search()
	{
		if($this->search_criteria == "")
			return $this->SearchBasic();
		
		$query = "SELECT * FROM `{$this->obj->_dbo_table}` WHERE {$this->search_criteria}";
		$query .= $this->GetOrderClause() . " " . $this->GetLimitClause();
		
		return new SimpleDBOResultSet($this->sql->Query($query));
	}
	
	/*!
		\brief Performs a basic SELECT statement on the table
		\returns ReadOnlyResultSet instance if successful, false on failure
	*/
	private function SearchBasic()
	{
		$query = "SELECT * FROM `{$this->obj->_dbo_table}` WHERE ";
		$columns = $this->obj->GetColumnNames();
		$conditions = array();
		
		// If the user has set class properties in this object, use them as search terms
		foreach($columns as $column)
			if($this->obj->$column != "")
				$conditions[] .= "`{$column}`='" . $this->sql->Escape($this->obj->$column) . "'";
				
		// If conditions is non-empty, search terms (above) are present
		if(count($conditions) > 0)
			$query .= implode($conditions, "AND ");
		else // Otherwise, just get everything from the database
			$query .= "1 ";
		
		// Finish the rest of the query with the ORDER BY and LIMIT statements (if the user has set any of that
		// information with $this->SetSortOrder or $this->SetLimit
		$query .= " " . $this->GetOrderClause() . " " . $this->GetLimitClause();
		
		return new SimpleDBOResultSet($this->sql->Query($query));
	}
	
	/*!
		\brief Constructs the ORDER BY clause (for searching)
		\returns nothing
		
		To be used exlusively by the functoins that perform searches.
	*/
	private function GetOrderClause()
	{
		return ($this->sort_col != "") ? "ORDER BY `{$this->sort_col}` {$this->sort_order}" : "";
	}
	
	/*!
		\brief Constructs the LIMIT clause (for searching)
		\returns nothing
		
		To be used exlusively by the functoins that perform searches.
	*/
	private function GetLimitClause()
	{
		$clause  = ($this->limit_offset !== "") ? "LIMIT {$this->limit_offset}" : "";
		$clause .= ($clause != "" && $this->limit_count !== "") ? ", {$this->limit_count}" : "";
		return $clause;
	}
}
?>